﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NCP.Recruiting.ApplicationServices.Interfaces;
using NCP.Recruiting.Domain.Aggregates.Companies;
using NCP.Recruiting.ApplicationServices.Messaging.Companies;
using NCP.Recruiting.ApplicationServices.ViewModels;
using NCP.Recruiting.ApplicationServices.ModelConversions;
using NCP.Recruiting.ApplicationServices.Messaging;
using NCP.Recruiting.ApplicationServices.Contracts;
using NCP.Infrastructure.Common;
using NCP.Recruiting.ApplicationServices.Exceptions;

namespace NCP.Recruiting.ApplicationServices.Implementations
{
    public class CompanyAppService : ICompanyAppService
    {
        private readonly ICompanyRepository _companyRepository;

        public CompanyAppService(ICompanyRepository companyRepository)
        {
            this._companyRepository = companyRepository;
        }

        public GetCompaniesResponse GetAll()
        {
            var response = new GetCompaniesResponse();
            IEnumerable<Company> allCompanies = _companyRepository.GetPaged(1, 10, CompanySpecifications.EmployeesMoreThan(1000), c => c.DateCreated, false);
            response.Companies = allCompanies.ConvertToViewModels();

            return response;
        }

        public ValidateUserResponse ValidateUser(ValidateUserRequest request)
        {
            var company = this._companyRepository.GetCompanyByName(request.Username);
            ValidateUserResponse response = new ValidateUserResponse();

            response.Success = false;
            if (company != null)
            {
                if (company.Password == request.Password)
                {
                    response.Success = true;
                    response.AuthenticatedUser = company.ConvertToUserViewModel();
                }
            }

            return response;
        }


        public GetUserResponse GetUser(GetUserRequest request)
        {
            GetUserResponse response = new GetUserResponse();

            response.AuthenticatedUser = _companyRepository.Get(request.Id).ConvertToUserViewModel();

            return response;
        }


        public RegisterUserResponse RegisterUser(RegisterUserRequest request)
        {
            Company newCompany = AssignToDomain(request.RegisterFormModel);
            ThrowExceptionIfCompanyIsInvalid(newCompany);

            try
            {
                newCompany.GenerateNewIdentity();
                _companyRepository.Add(newCompany);
                _companyRepository.UnitOfWork.Commit();

                return new RegisterUserResponse
                {
                    AuthenticatedUser = _companyRepository.Get(newCompany.Id).ConvertToUserViewModel(),
                    Success = true
                };
            }
            catch (Exception ex)
            {
                return new RegisterUserResponse() { Exception = ex };
            }

        }

        private Company AssignToDomain(ICreateUserCommand formModel)
        {
            return new Company
            {
                Username = formModel.Username,
                Password = formModel.Password,
                PasswordSalt = formModel.Password,
                CompanyName = formModel.CompanyName,
                Tel = formModel.Tel,
                Contact = formModel.Contact,
                Mobile = formModel.Mobile,
                LastUpdated = DateTime.Now,
                DateCreated = DateTime.Now,
                Deleted = false
            };
        }

        private void ThrowExceptionIfCompanyIsInvalid(Company newCompany)
        {

        }

        public ChangePasswordResponse ChangePassword(ChangePasswordRequest request)
        {
            try
            {
                Company existingCompany = _companyRepository.Get(request.Id);

                if (existingCompany != null)
                {
                    existingCompany.Password = request.ChangePasswordProperties.NewPassword;

                    _companyRepository.Modify(existingCompany);
                    _companyRepository.UnitOfWork.Commit();

                    return new ChangePasswordResponse();
                }
                else
                {
                    return new ChangePasswordResponse { Exception = GetStandardRecordNotFoundException() };
                }
            }
            catch (Exception ex)
            {
                return new ChangePasswordResponse { Exception = ex };
            }
        }

        private ResourceNotFoundException GetStandardRecordNotFoundException()
        {
            return new ResourceNotFoundException("The requested company was not found.");
        }

        public GetInfoByIdResponse GetInfoById(GetInfoByIdRequest request)
        {
            var company = this._companyRepository.Get(request.Id);
            var companyInfo = company.CopyItem<Company, CompanyInfo>();
            return new GetInfoByIdResponse() { CompanyInfo = companyInfo };
        }

        public GetCompanyResponse GetCompanyById(GetCompanyRequest requeset)
        {

            var company = this._companyRepository.AllMatching(CompanySpecifications.GetByCompanyId(requeset.Id)).FirstOrDefault();
            var companyitem = company.CopyItem<Company, CompanyViewModel>();
            companyitem.Id = company.Id;
            return new GetCompanyResponse() { Company = companyitem };




        }

        public UpdateCompanyResponse UpdateCompany(UpdateCompanyRequest request)
        {
            var response = new UpdateCompanyResponse();
            try
            {
                var companyItem = _companyRepository.Get(request.CompanyForm.Id);
                companyItem.CompanyName = request.CompanyForm.CompanyName;
                companyItem.ShortName = request.CompanyForm.ShortName;
                companyItem.Shortcut = request.CompanyForm.Shortcut;
                companyItem.Industry = request.CompanyForm.Industry;
                companyItem.CompanyType = request.CompanyForm.CompanyType;
                companyItem.Employees = request.CompanyForm.Employees;
                companyItem.BusinessLicense = request.CompanyForm.BusinessLicense;
                companyItem.RegisteredCapital = request.CompanyForm.RegisteredCapital;
                companyItem.EstablishedOn = request.CompanyForm.EstablishedOn;
                companyItem.Overview = request.CompanyForm.Overview;
                companyItem.Business = request.CompanyForm.Business;
                companyItem.Province = request.CompanyForm.Province;
                companyItem.City = request.CompanyForm.City;
                companyItem.Address = request.CompanyForm.Address;
                companyItem.PostalCode = request.CompanyForm.PostalCode;
                companyItem.Contact = request.CompanyForm.Contact;
                companyItem.Tel = request.CompanyForm.Tel;
                companyItem.Fax = request.CompanyForm.Fax;
                companyItem.Mobile = request.CompanyForm.Mobile;
                companyItem.Email = request.CompanyForm.Email;
                companyItem.WebSite = request.CompanyForm.WebSite;
                companyItem.Park = request.CompanyForm.Park;
                if (request.CompanyForm.Logo != null)
                {
                    companyItem.Logo = request.CompanyForm.Logo;
                }
                companyItem.EnableShortName = request.CompanyForm.EnableShortName;

                //companyItem.Template = request.CompanyForm.TemplateId;

                _companyRepository.Modify(companyItem);
                _companyRepository.UnitOfWork.Commit();
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }

        public UpdateCompanyResponse UpdateCompanyLogo(UpdateCompanyRequest request)
        {
            var response = new UpdateCompanyResponse();
            try
            {
                var companyItem = _companyRepository.Get(request.CompanyForm.Id);
                companyItem.Logo = null;

                _companyRepository.Modify(companyItem);
                _companyRepository.UnitOfWork.Commit();
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
    }
}
